<template>
  <div
    class="scroll-wrapper"
    ref="refScroll"
    @scroll="hInput_debounce_with_lodash"
  >
    <van-pull-refresh
      v-model="isPullLoading"
      @refresh="onRefresh"
    >
      <!--
          van-list自带上拉加载更多 的效果
          原理：
            1）数据项在list中
            2）在显示数据时，如果当前的数据不足一屏，它会自动触发load事件，并执行对应的回调onLoad去加载数据在onload中，通过ajax取回新数据
              - 把数据追加到list中（list的内容会越来越多）
              - 把loading手动设置为false
              - 判断是否所有的数据已经加载完成，如果是，则把finished设为true
            3) 如果手动向上拉，且finished不为true, 也会去调用onLoad
      -->
      <van-list
        v-model="loading"
        :finished="finished"
        finished-text="我是有底线的"
        @load="onLoad"
      >
        <van-cell
          v-for="article in list"
          :key="article.art_id.toString()"
          :title="article.title"
          @click="$router.push('/article/' + article.art_id.toString())"
        >
          <div slot="label">
            <!-- 图片区域 -->
            <van-grid :column-num="article.cover.images.length">
              <van-grid-item
                v-for="(value,idx) in article.cover.images"
                :key="idx"
              >
                <van-image
                  lazy-load
                  :src="value"
                />
              </van-grid-item>
            </van-grid>
            <!-- 文字区域 -->
            <div class="meta">
              <span>{{article.aut_name}}</span>
              <span>{{article.comm_count}}评论</span>
              <span>{{article.pubdate | relativeTime}}</span>
              <!-- 如果是登陆用户(有没有token)，则显示x按钮 -->
              <span
                class="close"
                v-if="$store.state.tokenInfo.token"
                @click="hShowMoreAction(article)"
              >
                <van-icon name="cross"></van-icon>
              </span>
            </div>
          </div>
        </van-cell>
      </van-list>
    </van-pull-refresh>

    <!-- 更多操作-弹层 -->
    <!-- moreAction组件只有当van-popup显示时，才会去创建 -->
    <van-popup
      v-model="isShowMoreAction"
      :style="{ width: '80%' }"
    >
      <!-- 更多操作 -->
      <!-- 添加ref属性是为了能够在父组件aticleList.vue中通过this.$refs.moreAction来获取more-action组件的引用 -->
      <!-- 在子组件监听 不感兴趣 -->
      <!-- 在子组件监听 举报文章 -->
      <more-action
        ref="moreAction"
        @un-like='hUnlike'
        @report="hReport"
      ></more-action>
    </van-popup>
  </div>
</template>

<script>
import MoreAction from './moreAction'
import { getArticles, unLike, report } from '@/api/article'
// 引入带节流防抖函数的lodash包
import _ from 'lodash'
export default {
  components: { MoreAction },
  name: 'ArticleList',
  props: ['channel'],
  data () {
    return {
      isShowMoreAction: false, // 是否显示更多操作弹层组件
      timestamp: Date.now(), // 当前时间戳
      list: [], // 数据列表
      loading: false, // 上拉是否正在加载...
      finished: false, // 是否所有的数据全部加载完成
      isPullLoading: false, // 下拉是否正在加载...
      articleId: '' // 当前要操作的文章的编号
    }
  },
  activated () {
    console.log('激活 activated...')
    if (this.scrollTop) {
      this.$refs.refScroll.scrollTop = this.scrollTop
    }
  },
  methods: {
    // 防抖函数
    hInput_debounce_with_lodash: _.debounce(function () {
      // this.hInput()
      this.hScroll()
    }, 0.5 * 1000),
    // 监听滚动事件
    hScroll () {
      console.log(this.$refs.refScroll.scrollTop)
      // 对象普通的属性， 不是响应式的数据
      this.scrollTop = this.$refs.refScroll.scrollTop
    },
    // 用户点击了举报
    async hReport (reportTypeId) {
      try {
        // 1 发请求 举报
        await report(this.articleId, reportTypeId) // reportTypeId 收到的举报类型
        // 2 删除文章: 根据文章的编号在list中删除
        this.delArticle(this.articleId)
        // 3 关闭弹层
        this.isShowMoreAction = false
        this.$toast.success('操作成功')
      } catch (err) {
        console.log(err)
        this.$toast.fail('操作失败')
      }
    },
    // 用户点击了不感兴趣
    async hUnlike () {
      try {
        // 1. 调用接口发请求，传文章编号
        await unLike(this.articleId)
        // 2 删除文章: 根据文章的编号在list中删除
        this.delArticle(this.articleId)
        // 3 关闭弹层
        this.isShowMoreAction = false
        this.$toast.success('操作成功')
      } catch (err) {
        this.$toast.fail('操作失败')
      }
    },
    // 删除文章
    delArticle (articleId) {
      // 1. 查找：用findIndex，在list中找到 编号=== articleId的那个文章 返回下标
      const idx = this.list.findIndex((article) => {
        return article.art_id.toString() === articleId
      })
      // 如果有找到，则返回值就是下标；如果找不到返回-1
      if (idx !== -1) {
        // 2. 删除(splice)
        this.list.splice(idx, 1)
      }
    },
    // 用户点击了叉号
    hShowMoreAction (article) {
      // 1 显示更多操作弹层
      this.isShowMoreAction = true
      // 2 记下当前被操作的文章的编号
      this.articleId = article.art_id.toString() // article.art_id可能是一个Bigint对象，所以用toString()转成字符串
      // 3 把子组件MoreAction中的isReport改成false
      // 因为第一次打开弹层时，子组件并没有被创建出来，所以这里要先判断一下
      if (this.$refs.moreAction) {
        // 用ref获取子组件的引用，然后通过引用来修改子组件中的数据
        this.$refs.moreAction.isReport = false
      }
    },
    // 下拉刷新获取最新的数据添加到列表中（数组头部）
    async onRefresh () {
      // 1.发ajax获取最新数据
      const res = await getArticles(this.channel.id, Date.now()) // 当前时间戳
      const arr = res.data.data.results
      // 2. 把数据添加到list中 unshift是把数据放在数组的头部
      this.list.unshift(...arr)
      // 3. 更新loading
      this.isPullLoading = false
    },
    // 上拉获取数据添加到数据列表中（数组末尾）
    async onLoad () {
      // 1 发ajax取数据
      const res = await getArticles(this.channel.id, this.timestamp) // 保存的时间戳
      const arr = res.data.data.results // 返回数据本身是一个数组
      //  把求回数据的时间戳存起来
      this.timestamp = res.data.data.pre_timestamp
      // 2 把arr中的数据追加到list中 arr是一个对象数组 ...是展开运算符  push是把数据放在数组的末尾
      this.list.push(...arr)
      // 3 手动把loading设置为false
      this.loading = false
      // 4 判断是否所有的数据全部加载完成
      if (arr.length === 0) {
        this.finished = true
      }
    }
  }
}
</script>

<style scoped lang='less'>
.meta {
  span {
    margin-right: 10px;
  }
  display: flex;
  .close {
    // 让它在最右边
    // 它的父级容器是flex的，给当前元素设置左外边距为auto，会让这个元素在父级容器
    // 的最右边
    margin-left: auto;
  }
}
</style>
